/**
 * index_iterator.cpp
 */
#include <cassert>

#include "storage/index/index_iterator.h"

namespace bustub {

/*
 * NOTE: you can change the destructor/constructor method here
 * set your own input parameters
 */
INDEX_TEMPLATE_ARGUMENTS
INDEXITERATOR_TYPE::IndexIterator(BufferPoolManager *bpm, ReadPageGuard &&guard, ReadPageGuard &&head, int index)
    : bpm_(bpm), guard_(std::move(guard)), head_(std::move(head)), index_(index) {
  if (bpm_ != nullptr && index != -1) {
    pg_id_ = guard_.PageId();
  } else {
    pg_id_ = INVALID_PAGE_ID;
  }
}

INDEX_TEMPLATE_ARGUMENTS
INDEXITERATOR_TYPE::~IndexIterator() = default;  // NOLINT

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::IsEnd() -> bool { return pg_id_ == INVALID_PAGE_ID; }

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::operator*() -> const MappingType & {
  auto *leaf = guard_.As<BPlusTreeLeafPage<KeyType, ValueType, KeyComparator>>();
  // std::cout << leaf->KeyAt(index_) << std::endl;
  return leaf->GetLeafMappingType(index_);
}

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::operator++() -> INDEXITERATOR_TYPE & {
  // std::cout << "iterator++" << std::endl;
  if (!IsEnd()) {
    auto *leaf = guard_.As<BPlusTreeLeafPage<KeyType, ValueType, KeyComparator>>();
    index_++;
    if (index_ == leaf->GetSize()) {
      if (leaf->GetNextPageId() == INVALID_PAGE_ID) {
        bpm_ = nullptr;
        index_ = -1;
        guard_.Drop();
        head_.Drop();
        pg_id_ = INVALID_PAGE_ID;
        return *this;
      }
      guard_ = bpm_->FetchPageRead(leaf->GetNextPageId());
      index_ = 0;
      pg_id_ = guard_.PageId();
    }
  }
  return *this;
}

template class IndexIterator<GenericKey<4>, RID, GenericComparator<4>>;

template class IndexIterator<GenericKey<8>, RID, GenericComparator<8>>;

template class IndexIterator<GenericKey<16>, RID, GenericComparator<16>>;

template class IndexIterator<GenericKey<32>, RID, GenericComparator<32>>;

template class IndexIterator<GenericKey<64>, RID, GenericComparator<64>>;

}  // namespace bustub
